home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / Mesa-3.0 / SRC / SPAN.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-16  |  29.8 KB  |  1,074 lines

  1. /* $Id: span.c,v 3.9 1998/08/16 14:45:44 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.0
  6.  * Copyright (C) 1995-1998  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: span.c,v $
  26.  * Revision 3.9  1998/08/16 14:45:44  brianp
  27.  * fixed clipping problem in gl_read_rgba_span() (Karl Schultz)
  28.  *
  29.  * Revision 3.8  1998/06/07 22:18:52  brianp
  30.  * implemented GL_EXT_multitexture extension
  31.  *
  32.  * Revision 3.7  1998/03/28 03:57:13  brianp
  33.  * added CONST macro to fix IRIX compilation problems
  34.  *
  35.  * Revision 3.6  1998/03/27 04:17:31  brianp
  36.  * fixed G++ warnings
  37.  *
  38.  * Revision 3.5  1998/03/15 17:55:54  brianp
  39.  * added FogMode to context struct
  40.  *
  41.  * Revision 3.4  1998/03/10 01:27:47  brianp
  42.  * fixed bugs in the backup of color arrays
  43.  *
  44.  * Revision 3.3  1998/02/20 04:50:44  brianp
  45.  * implemented GL_SGIS_multitexture
  46.  *
  47.  * Revision 3.2  1998/02/03 04:26:07  brianp
  48.  * removed const from lambda[] passed to gl_write_texture_span()
  49.  *
  50.  * Revision 3.1  1998/02/02 03:09:34  brianp
  51.  * added GL_LIGHT_MODEL_COLOR_CONTROL (separate specular color interpolation)
  52.  *
  53.  * Revision 3.0  1998/01/31 21:03:42  brianp
  54.  * initial rev
  55.  *
  56.  */
  57.  
  58.  
  59. /*
  60.  * pixel span rasterization:
  61.  * These functions simulate the rasterization pipeline.
  62.  */
  63.  
  64.  
  65. #ifdef PC_HEADER
  66. #include "all.h"
  67. #else
  68. #include <assert.h>
  69. #include <string.h>
  70. #include "alpha.h"
  71. #include "alphabuf.h"
  72. #include "blend.h"
  73. #include "depth.h"
  74. #include "fog.h"
  75. #include "logic.h"
  76. #include "macros.h"
  77. #include "masking.h"
  78. #include "scissor.h"
  79. #include "span.h"
  80. #include "stencil.h"
  81. #include "texture.h"
  82. #include "types.h"
  83. #endif
  84.  
  85.  
  86.  
  87.  
  88. /*
  89.  * Apply the current polygon stipple pattern to a span of pixels.
  90.  */
  91. static void stipple_polygon_span( GLcontext *ctx,
  92.                                   GLuint n, GLint x, GLint y, GLubyte mask[] )
  93. {
  94.    register GLuint i, m, stipple, highbit=0x80000000;
  95.  
  96.    stipple = ctx->PolygonStipple[y % 32];
  97.    m = highbit >> (GLuint) (x % 32);
  98.  
  99.    for (i=0;i<n;i++) {
  100.       if ((m & stipple)==0) {
  101.      mask[i] = 0;
  102.       }
  103.       m = m >> 1;
  104.       if (m==0) {
  105.      m = 0x80000000;
  106.       }
  107.    }
  108. }
  109.  
  110.  
  111.  
  112. /*
  113.  * Clip a pixel span to the current buffer/window boundaries.
  114.  * Return:  0 = all pixels clipped
  115.  *          1 = at least one pixel is visible
  116.  */
  117. static GLuint clip_span( GLcontext *ctx,
  118.                          GLint n, GLint x, GLint y, GLubyte mask[] )
  119. {
  120.    GLint i;
  121.  
  122.    /* Clip to top and bottom */
  123.    if (y<0 || y>=ctx->Buffer->Height) {
  124.       return 0;
  125.    }
  126.  
  127.    /* Clip to left and right */
  128.    if (x>=0 && x+n<=ctx->Buffer->Width) {
  129.       /* no clipping needed */
  130.       return 1;
  131.    }
  132.    else if (x+n<=0) {
  133.       /* completely off left side */
  134.       return 0;
  135.    }
  136.    else if (x>=ctx->Buffer->Width) {
  137.       /* completely off right side */
  138.       return 0;
  139.    }
  140.    else {
  141.       /* clip-test each pixel, this could be done better */
  142.       for (i=0;i<n;i++) {
  143.          if (x+i<0 || x+i>=ctx->Buffer->Width) {
  144.             mask[i] = 0;
  145.          }
  146.       }
  147.       return 1;
  148.    }
  149. }
  150.  
  151.  
  152.  
  153. /*
  154.  * Write a horizontal span of color index pixels to the frame buffer.
  155.  * Stenciling, Depth-testing, etc. are done as needed.
  156.  * Input:  n - number of pixels in the span
  157.  *         x, y - location of leftmost pixel in the span
  158.  *         z - array of [n] z-values
  159.  *         index - array of [n] color indexes
  160.  *         primitive - either GL_POINT, GL_LINE, GL_POLYGON, or GL_BITMAP
  161.  */
  162. void gl_write_index_span( GLcontext *ctx,
  163.                           GLuint n, GLint x, GLint y, const GLdepth z[],
  164.               GLuint indexIn[], GLenum primitive )
  165. {
  166.    GLubyte mask[MAX_WIDTH];
  167.    GLuint indexBackup[MAX_WIDTH];
  168.    GLuint *index;  /* points to indexIn or indexBackup */
  169.  
  170.    /* init mask to 1's (all pixels are to be written) */
  171.    MEMSET(mask, 1, n);
  172.  
  173.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  174.       if (clip_span(ctx,n,x,y,mask)==0) {
  175.      return;
  176.       }
  177.    }
  178.  
  179.    if ((primitive==GL_BITMAP && ctx->MutablePixels)
  180.        || (ctx->RasterMask & FRONT_AND_BACK_BIT)) {
  181.       /* Make copy of color indexes */
  182.       MEMCPY( indexBackup, indexIn, n * sizeof(GLuint) );
  183.       index = indexBackup;
  184.    }
  185.    else {
  186.       index = indexIn;
  187.    }
  188.  
  189.    /* Per-pixel fog */
  190.    if (ctx->Fog.Enabled && (primitive==GL_BITMAP || ctx->FogMode == FOG_FRAGMENT)) {
  191.       gl_fog_ci_pixels( ctx, n, z, index );
  192.    }
  193.  
  194.    /* Do the scissor test */
  195.    if (ctx->Scissor.Enabled) {
  196.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  197.      return;
  198.       }
  199.    }
  200.  
  201.    /* Polygon Stippling */
  202.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  203.       stipple_polygon_span( ctx, n, x, y, mask );
  204.    }
  205.  
  206.    if (ctx->Stencil.Enabled) {
  207.       /* first stencil test */
  208.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  209.      return;
  210.       }
  211.       /* depth buffering w/ stencil */
  212.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  213.    }
  214.    else if (ctx->Depth.Test) {
  215.       /* regular depth testing */
  216.       if ((*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask )==0)  return;
  217.    }
  218.  
  219.    if (ctx->RasterMask & NO_DRAW_BIT) {
  220.       /* write no pixels */
  221.       return;
  222.    }
  223.  
  224.    if (ctx->Color.SWLogicOpEnabled) {
  225.       gl_logicop_ci_span( ctx, n, x, y, index, mask );
  226.    }
  227.    if (ctx->Color.SWmasking) {
  228.       gl_mask_index_span( ctx, n, x, y, index );
  229.    }
  230.  
  231.    /* write pixels */
  232.    (*ctx->Driver.WriteCI32Span)( ctx, n, x, y, index, mask );
  233.  
  234.  
  235.    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  236.       /*** Also draw to back buffer ***/
  237.       (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  238.       MEMCPY( indexBackup, indexIn, n * sizeof(GLuint) );
  239.       assert( index == indexBackup );
  240.       if (ctx->Color.SWLogicOpEnabled) {
  241.          gl_logicop_ci_span( ctx, n, x, y, index, mask );
  242.       }
  243.       if (ctx->Color.SWmasking) {
  244.          gl_mask_index_span( ctx, n, x, y, index );
  245.       }
  246.       (*ctx->Driver.WriteCI32Span)( ctx, n, x, y, index, mask );
  247.       (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  248.    }
  249. }
  250.  
  251.  
  252.  
  253.  
  254. void gl_write_monoindex_span( GLcontext *ctx,
  255.                               GLuint n, GLint x, GLint y, const GLdepth z[],
  256.                   GLuint index, GLenum primitive )
  257. {
  258.    GLuint i;
  259.    GLubyte mask[MAX_WIDTH];
  260.    GLuint indexBackup[MAX_WIDTH];
  261.  
  262.    /* init mask to 1's (all pixels are to be written) */
  263.    MEMSET(mask, 1, n);
  264.  
  265.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  266.       if (clip_span( ctx, n, x, y, mask)==0) {
  267.      return;
  268.       }
  269.    }
  270.  
  271.    /* Do the scissor test */
  272.    if (ctx->Scissor.Enabled) {
  273.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  274.      return;
  275.       }
  276.    }
  277.  
  278.    /* Polygon Stippling */
  279.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  280.       stipple_polygon_span( ctx, n, x, y, mask );
  281.    }
  282.  
  283.    if (ctx->Stencil.Enabled) {
  284.       /* first stencil test */
  285.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  286.      return;
  287.       }
  288.       /* depth buffering w/ stencil */
  289.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  290.    }
  291.    else if (ctx->Depth.Test) {
  292.       /* regular depth testing */
  293.       if ((*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask )==0)  return;
  294.    }
  295.  
  296.    if (ctx->RasterMask & NO_DRAW_BIT) {
  297.       /* write no pixels */
  298.       return;
  299.    }
  300.  
  301.    if ((ctx->Fog.Enabled && (primitive==GL_BITMAP || ctx->FogMode==FOG_FRAGMENT))
  302.         || ctx->Color.SWLogicOpEnabled || ctx->Color.SWmasking) {
  303.       GLuint ispan[MAX_WIDTH];
  304.       /* index may change, replicate single index into an array */
  305.       for (i=0;i<n;i++) {
  306.      ispan[i] = index;
  307.       }
  308.  
  309.       if (ctx->Fog.Enabled && (primitive==GL_BITMAP || ctx->FogMode==FOG_FRAGMENT)) {
  310.      gl_fog_ci_pixels( ctx, n, z, ispan );
  311.       }
  312.  
  313.       if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  314.          MEMCPY( indexBackup, ispan, n * sizeof(GLuint) );
  315.       }
  316.  
  317.       if (ctx->Color.SWLogicOpEnabled) {
  318.      gl_logicop_ci_span( ctx, n, x, y, ispan, mask );
  319.       }
  320.  
  321.       if (ctx->Color.SWmasking) {
  322.          gl_mask_index_span( ctx, n, x, y, ispan );
  323.       }
  324.  
  325.       (*ctx->Driver.WriteCI32Span)( ctx, n, x, y, ispan, mask );
  326.  
  327.       if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  328.          /*** Also draw to back buffer ***/
  329.          MEMCPY( ispan, indexBackup, n * sizeof(GLuint) );
  330.          (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  331.          for (i=0;i<n;i++) {
  332.             ispan[i] = index;
  333.          }
  334.          if (ctx->Color.SWLogicOpEnabled) {
  335.             gl_logicop_ci_span( ctx, n, x, y, ispan, mask );
  336.          }
  337.          if (ctx->Color.SWmasking) {
  338.             gl_mask_index_span( ctx, n, x, y, ispan );
  339.          }
  340.          (*ctx->Driver.WriteCI32Span)( ctx, n, x, y, ispan, mask );
  341.          (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  342.       }
  343.    }
  344.    else {
  345.       (*ctx->Driver.WriteMonoCISpan)( ctx, n, x, y, mask );
  346.  
  347.       if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  348.          /*** Also draw to back buffer ***/
  349.          (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  350.          (*ctx->Driver.WriteMonoCISpan)( ctx, n, x, y, mask );
  351.          (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  352.       }
  353.    }
  354. }
  355.  
  356.  
  357.  
  358. void gl_write_rgba_span( GLcontext *ctx,
  359.                          GLuint n, GLint x, GLint y, const GLdepth z[],
  360.                          GLubyte rgbaIn[][4],
  361.                          GLenum primitive )
  362. {
  363.    GLubyte mask[MAX_WIDTH];
  364.    GLboolean write_all = GL_TRUE;
  365.    GLubyte rgbaBackup[MAX_WIDTH][4];
  366.    GLubyte (*rgba)[4];
  367.    const GLubyte *Null = 0;
  368.  
  369.    /* init mask to 1's (all pixels are to be written) */
  370.    MEMSET(mask, 1, n);
  371.  
  372.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  373.       if (clip_span( ctx,n,x,y,mask)==0) {
  374.      return;
  375.       }
  376.       write_all = GL_FALSE;
  377.    }
  378.  
  379.    if ((primitive==GL_BITMAP && ctx->MutablePixels)
  380.        || (ctx->RasterMask & FRONT_AND_BACK_BIT)) {
  381.       /* must make a copy of the colors since they may be modified */
  382.       MEMCPY( rgbaBackup, rgbaIn, 4 * n * sizeof(GLubyte) );
  383.       rgba = rgbaBackup;
  384.    }
  385.    else {
  386.       rgba = rgbaIn;
  387.    }
  388.  
  389.    /* Per-pixel fog */
  390.    if (ctx->Fog.Enabled && (primitive==GL_BITMAP || ctx->FogMode==FOG_FRAGMENT)) {
  391.       gl_fog_rgba_pixels( ctx, n, z, rgba );
  392.    }
  393.  
  394.    /* Do the scissor test */
  395.    if (ctx->Scissor.Enabled) {
  396.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  397.      return;
  398.       }
  399.       write_all = GL_FALSE;
  400.    }
  401.  
  402.    /* Polygon Stippling */
  403.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  404.       stipple_polygon_span( ctx, n, x, y, mask );
  405.       write_all = GL_FALSE;
  406.    }
  407.  
  408.    /* Do the alpha test */
  409.    if (ctx->Color.AlphaEnabled) {
  410.       if (gl_alpha_test( ctx, n, rgba, mask )==0) {
  411.      return;
  412.       }
  413.       write_all = GL_FALSE;
  414.    }
  415.  
  416.    if (ctx->Stencil.Enabled) {
  417.       /* first stencil test */
  418.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  419.      return;
  420.       }
  421.       /* depth buffering w/ stencil */
  422.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  423.       write_all = GL_FALSE;
  424.    }
  425.    else if (ctx->Depth.Test) {
  426.       /* regular depth testing */
  427.       GLuint m = (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
  428.       if (m==0) {
  429.          return;
  430.       }
  431.       if (m<n) {
  432.          write_all = GL_FALSE;
  433.       }
  434.    }
  435.  
  436.    if (ctx->RasterMask & NO_DRAW_BIT) {
  437.       /* write no pixels */
  438.       return;
  439.    }
  440.  
  441.    /* logic op or blending */
  442.    if (ctx->Color.SWLogicOpEnabled) {
  443.       gl_logicop_rgba_span( ctx, n, x, y, rgba, mask );
  444.    }
  445.    else if (ctx->Color.BlendEnabled) {
  446.       gl_blend_span( ctx, n, x, y, rgba, mask );
  447.    }
  448.  
  449.    /* Color component masking */
  450.    if (ctx->Color.SWmasking) {
  451.       gl_mask_rgba_span( ctx, n, x, y, rgba );
  452.    }
  453.  
  454.    /* write pixels */
  455.    (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, rgba, write_all ? Null : mask );
  456.    if (ctx->RasterMask & ALPHABUF_BIT) {
  457.       gl_write_alpha_span( ctx, n, x, y, rgba, write_all ? Null : mask );
  458.    }
  459.  
  460.    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  461.       /*** Also render to back buffer ***/
  462.       MEMCPY( rgbaBackup, rgbaIn, 4 * n * sizeof(GLubyte) );
  463.       assert( rgba == rgbaBackup );
  464.       (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  465.       if (ctx->Color.SWLogicOpEnabled) {
  466.          gl_logicop_rgba_span( ctx, n, x, y, rgba, mask );
  467.       }
  468.       else  if (ctx->Color.BlendEnabled) {
  469.          gl_blend_span( ctx, n, x, y, rgba, mask );
  470.       }
  471.       if (ctx->Color.SWmasking) {
  472.          gl_mask_rgba_span( ctx, n, x, y, rgba );
  473.       }
  474.       (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, rgba, write_all ? Null : mask );
  475.       if (ctx->RasterMask & ALPHABUF_BIT) {
  476.          ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  477.          gl_write_alpha_span( ctx, n, x, y, rgba, write_all ? Null : mask );
  478.          ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  479.       }
  480.       (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  481.    }
  482.  
  483. }
  484.  
  485.  
  486.  
  487. /*
  488.  * Write a horizontal span of color pixels to the frame buffer.
  489.  * The color is initially constant for the whole span.
  490.  * Alpha-testing, stenciling, depth-testing, and blending are done as needed.
  491.  * Input:  n - number of pixels in the span
  492.  *         x, y - location of leftmost pixel in the span
  493.  *         z - array of [n] z-values
  494.  *         r, g, b, a - the color of the pixels
  495.  *         primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
  496.  */
  497. void gl_write_monocolor_span( GLcontext *ctx,
  498.                               GLuint n, GLint x, GLint y, const GLdepth z[],
  499.                   GLint r, GLint g, GLint b, GLint a,
  500.                               GLenum primitive )
  501. {
  502.    GLuint i;
  503.    GLubyte mask[MAX_WIDTH];
  504.    GLboolean write_all = GL_TRUE;
  505.    GLubyte rgba[MAX_WIDTH][4];
  506.    const GLubyte *Null = 0;
  507.  
  508.    /* init mask to 1's (all pixels are to be written) */
  509.    MEMSET(mask, 1, n);
  510.  
  511.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  512.       if (clip_span( ctx,n,x,y,mask)==0) {
  513.      return;
  514.       }
  515.       write_all = GL_FALSE;
  516.    }
  517.  
  518.    /* Do the scissor test */
  519.    if (ctx->Scissor.Enabled) {
  520.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  521.      return;
  522.       }
  523.       write_all = GL_FALSE;
  524.    }
  525.  
  526.    /* Polygon Stippling */
  527.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  528.       stipple_polygon_span( ctx, n, x, y, mask );
  529.       write_all = GL_FALSE;
  530.    }
  531.  
  532.    /* Do the alpha test */
  533.    if (ctx->Color.AlphaEnabled) {
  534.       for (i=0;i<n;i++) {
  535.          rgba[i][ACOMP] = a;
  536.       }
  537.       if (gl_alpha_test( ctx, n, rgba, mask )==0) {
  538.      return;
  539.       }
  540.       write_all = GL_FALSE;
  541.    }
  542.  
  543.    if (ctx->Stencil.Enabled) {
  544.       /* first stencil test */
  545.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  546.      return;
  547.       }
  548.       /* depth buffering w/ stencil */
  549.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  550.       write_all = GL_FALSE;
  551.    }
  552.    else if (ctx->Depth.Test) {
  553.       /* regular depth testing */
  554.       GLuint m = (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
  555.       if (m==0) {
  556.          return;
  557.       }
  558.       if (m<n) {
  559.          write_all = GL_FALSE;
  560.       }
  561.    }
  562.  
  563.    if (ctx->RasterMask & NO_DRAW_BIT) {
  564.       /* write no pixels */
  565.       return;
  566.    }
  567.  
  568.    if (ctx->Color.BlendEnabled || ctx->Color.SWLogicOpEnabled
  569.        || ctx->Color.SWmasking) {
  570.       /* assign same color to each pixel */
  571.       for (i=0;i<n;i++) {
  572.      if (mask[i]) {
  573.         rgba[i][RCOMP] = r;
  574.         rgba[i][GCOMP] = g;
  575.         rgba[i][BCOMP] = b;
  576.         rgba[i][ACOMP] = a;
  577.      }
  578.       }
  579.  
  580.       if (ctx->Color.SWLogicOpEnabled) {
  581.          gl_logicop_rgba_span( ctx, n, x, y, rgba, mask );
  582.       }
  583.       else if (ctx->Color.BlendEnabled) {
  584.          gl_blend_span( ctx, n, x, y, rgba, mask );
  585.       }
  586.  
  587.       /* Color component masking */
  588.       if (ctx->Color.SWmasking) {
  589.          gl_mask_rgba_span( ctx, n, x, y, rgba );
  590.       }
  591.  
  592.       /* write pixels */
  593.       (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, rgba, write_all ? Null : mask );
  594.       if (ctx->RasterMask & ALPHABUF_BIT) {
  595.          gl_write_alpha_span( ctx, n, x, y, rgba, write_all ? Null : mask );
  596.       }
  597.  
  598.       if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  599.          /*** Also draw to back buffer ***/
  600.          for (i=0;i<n;i++) {
  601.             if (mask[i]) {
  602.                rgba[i][RCOMP] = r;
  603.                rgba[i][GCOMP] = g;
  604.                rgba[i][BCOMP] = b;
  605.                rgba[i][ACOMP] = a;
  606.             }
  607.          }
  608.          (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  609.          if (ctx->Color.SWLogicOpEnabled) {
  610.             gl_logicop_rgba_span( ctx, n, x, y, rgba, mask);
  611.          }
  612.          else if (ctx->Color.BlendEnabled) {
  613.             gl_blend_span( ctx, n, x, y, rgba, mask );
  614.          }
  615.          if (ctx->Color.SWmasking) {
  616.             gl_mask_rgba_span( ctx, n, x, y, rgba );
  617.          }
  618.          (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, rgba, write_all ? Null : mask );
  619.          (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  620.          if (ctx->RasterMask & ALPHABUF_BIT) {
  621.             ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  622.             gl_write_alpha_span( ctx, n, x, y, rgba,
  623.                                  write_all ? Null : mask );
  624.             ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  625.          }
  626.       }
  627.    }
  628.    else {
  629.       (*ctx->Driver.WriteMonoRGBASpan)( ctx, n, x, y, mask );
  630.       if (ctx->RasterMask & ALPHABUF_BIT) {
  631.          gl_write_mono_alpha_span( ctx, n, x, y, a, write_all ? Null : mask );
  632.       }
  633.       if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  634.          /* Also draw to back buffer */
  635.          (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  636.          (*ctx->Driver.WriteMonoRGBASpan)( ctx, n, x, y, mask );
  637.          (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  638.          if (ctx->RasterMask & ALPHABUF_BIT) {
  639.             ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  640.             gl_write_mono_alpha_span( ctx, n, x, y, a,
  641.                                       write_all ? Null : mask );
  642.             ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  643.          }
  644.       }
  645.    }
  646. }
  647.  
  648.  
  649.  
  650. /*
  651.  * Add specular color to base color.  This is used only when
  652.  * GL_LIGHT_MODEL_COLOR_CONTROL = GL_SEPARATE_SPECULAR_COLOR.
  653.  */
  654. static void add_colors(GLuint n, GLubyte rgba[][4], CONST GLubyte specular[][4] )
  655. {
  656.    GLuint i;
  657.    for (i=0; i<n; i++) {
  658.       GLint r = rgba[i][RCOMP] + specular[i][RCOMP];
  659.       GLint g = rgba[i][GCOMP] + specular[i][GCOMP];
  660.       GLint b = rgba[i][BCOMP] + specular[i][BCOMP];
  661.       rgba[i][RCOMP] = MIN2(r, 255);
  662.       rgba[i][GCOMP] = MIN2(g, 255);
  663.       rgba[i][BCOMP] = MIN2(b, 255);
  664.    }
  665. }
  666.  
  667.  
  668. /*
  669.  * Write a horizontal span of textured pixels to the frame buffer.
  670.  * The color of each pixel is different.
  671.  * Alpha-testing, stenciling, depth-testing, and blending are done
  672.  * as needed.
  673.  * Input:  n - number of pixels in the span
  674.  *         x, y - location of leftmost pixel in the span
  675.  *         z - array of [n] z-values
  676.  *         s, t - array of (s,t) texture coordinates for each pixel
  677.  *         lambda - array of texture lambda values
  678.  *         rgba - array of [n] color components
  679.  *         primitive - either GL_POINT, GL_LINE, GL_POLYGON or GL_BITMAP.
  680.  */
  681. void gl_write_texture_span( GLcontext *ctx,
  682.                             GLuint n, GLint x, GLint y, const GLdepth z[],
  683.                 const GLfloat s[], const GLfloat t[],
  684.                             const GLfloat u[], GLfloat lambda[],
  685.                 GLubyte rgbaIn[][4], CONST GLubyte spec[][4],
  686.                 GLenum primitive )
  687. {
  688.    GLubyte mask[MAX_WIDTH];
  689.    GLboolean write_all = GL_TRUE;
  690.    GLubyte rgbaBackup[MAX_WIDTH][4];
  691.    GLubyte (*rgba)[4];   /* points to either rgbaIn or rgbaBackup */
  692.    const GLubyte *Null = 0;
  693.  
  694.    /* init mask to 1's (all pixels are to be written) */
  695.    MEMSET(mask, 1, n);
  696.  
  697.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  698.       if (clip_span(ctx, n, x, y, mask)==0) {
  699.      return;
  700.       }
  701.       write_all = GL_FALSE;
  702.    }
  703.  
  704.  
  705.    if (primitive==GL_BITMAP || (ctx->RasterMask & FRONT_AND_BACK_BIT)) {
  706.       /* must make a copy of the colors since they may be modified */
  707.       MEMCPY(rgbaBackup, rgbaIn, 4 * sizeof(GLubyte));
  708.       rgba = rgbaBackup;
  709.    }
  710.    else {
  711.       rgba = rgbaIn;
  712.    }
  713.  
  714.    /* Texture */
  715.    ASSERT(ctx->Texture.Enabled);
  716.    gl_texture_pixels( ctx, 0, n, s, t, u, lambda, rgba );
  717.  
  718.    /* Add base and specular colors */
  719.    if (spec && ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
  720.       add_colors( n, rgba, spec );   /* rgba = rgba + spec */
  721.  
  722.    /* Per-pixel fog */
  723.    if (ctx->Fog.Enabled && (primitive==GL_BITMAP || ctx->FogMode==FOG_FRAGMENT)) {
  724.       gl_fog_rgba_pixels( ctx, n, z, rgba );
  725.    }
  726.  
  727.    /* Do the scissor test */
  728.    if (ctx->Scissor.Enabled) {
  729.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  730.      return;
  731.       }
  732.       write_all = GL_FALSE;
  733.    }
  734.  
  735.    /* Polygon Stippling */
  736.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  737.       stipple_polygon_span( ctx, n, x, y, mask );
  738.       write_all = GL_FALSE;
  739.    }
  740.  
  741.    /* Do the alpha test */
  742.    if (ctx->Color.AlphaEnabled) {
  743.       if (gl_alpha_test( ctx, n, rgba, mask )==0) {
  744.      return;
  745.       }
  746.       write_all = GL_FALSE;
  747.    }
  748.  
  749.    if (ctx->Stencil.Enabled) {
  750.       /* first stencil test */
  751.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  752.      return;
  753.       }
  754.       /* depth buffering w/ stencil */
  755.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  756.       write_all = GL_FALSE;
  757.    }
  758.    else if (ctx->Depth.Test) {
  759.       /* regular depth testing */
  760.       GLuint m = (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
  761.       if (m==0) {
  762.          return;
  763.       }
  764.       if (m<n) {
  765.          write_all = GL_FALSE;
  766.       }
  767.    }
  768.  
  769.    if (ctx->RasterMask & NO_DRAW_BIT) {
  770.       /* write no pixels */
  771.       return;
  772.    }
  773.  
  774.    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  775.       /* make backup of fragment colors */
  776.       MEMCPY( rgbaBackup, rgba, 4 * n * sizeof(GLubyte) );
  777.    }
  778.  
  779.    /* blending */
  780.    if (ctx->Color.SWLogicOpEnabled) {
  781.       gl_logicop_rgba_span( ctx, n, x, y, rgba, mask );
  782.    }
  783.    else  if (ctx->Color.BlendEnabled) {
  784.       gl_blend_span( ctx, n, x, y, rgba, mask );
  785.    }
  786.  
  787.    if (ctx->Color.SWmasking) {
  788.       gl_mask_rgba_span( ctx, n, x, y, rgba );
  789.    }
  790.  
  791.    /* write pixels */
  792.    (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, rgba, write_all ? Null : mask );
  793.    if (ctx->RasterMask & ALPHABUF_BIT) {
  794.       gl_write_alpha_span( ctx, n, x, y, rgba, write_all ? Null : mask );
  795.    }
  796.  
  797.    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  798.       /* Also draw to back buffer */
  799.       (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  800.       if (ctx->Color.SWLogicOpEnabled) {
  801.          gl_logicop_rgba_span( ctx, n, x, y, rgba, mask );
  802.       }
  803.       else if (ctx->Color.BlendEnabled) {
  804.          gl_blend_span( ctx, n, x, y, rgba, mask );
  805.       }
  806.       if (ctx->Color.SWmasking) {
  807.          gl_mask_rgba_span( ctx, n, x, y, rgba );
  808.       }
  809.       (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, rgba, write_all ? Null : mask );
  810.       (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  811.       if (ctx->RasterMask & ALPHABUF_BIT) {
  812.          ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  813.          gl_write_alpha_span( ctx, n, x, y, rgba, write_all ? Null : mask );
  814.          ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  815.       }
  816.    }
  817. }
  818.  
  819.  
  820.  
  821. /*
  822.  * As above but perform multiple stages of texture application.
  823.  * Input:  texSets - number of texture sets to apply
  824.  */
  825. void gl_write_multitexture_span( GLcontext *ctx, GLuint texSets,
  826.                                  GLuint n, GLint x, GLint y, const GLdepth z[],
  827.                                  CONST GLfloat s[][MAX_WIDTH],
  828.                                  CONST GLfloat t[][MAX_WIDTH],
  829.                                  CONST GLfloat u[][MAX_WIDTH],
  830.                                  GLfloat lambda[][MAX_WIDTH],
  831.                                  GLubyte rgbaIn[][4], CONST GLubyte spec[][4],
  832.                                  GLenum primitive )
  833. {
  834.    GLubyte mask[MAX_WIDTH];
  835.    GLboolean write_all = GL_TRUE;
  836.    GLubyte rgbaBackup[MAX_WIDTH][4];
  837.    GLubyte (*rgba)[4];   /* points to either rgbaIn or rgbaBackup */
  838.    GLuint i;
  839.    const GLubyte *Null = 0;
  840.  
  841.    /* init mask to 1's (all pixels are to be written) */
  842.    MEMSET(mask, 1, n);
  843.  
  844.    if ((ctx->RasterMask & WINCLIP_BIT) || primitive==GL_BITMAP) {
  845.       if (clip_span(ctx, n, x, y, mask)==0) {
  846.      return;
  847.       }
  848.       write_all = GL_FALSE;
  849.    }
  850.  
  851.  
  852.    if (primitive==GL_BITMAP || (ctx->RasterMask & FRONT_AND_BACK_BIT)) {
  853.       /* must make a copy of the colors since they may be modified */
  854.       MEMCPY(rgbaBackup, rgbaIn, 4 * sizeof(GLubyte));
  855.       rgba = rgbaBackup;
  856.    }
  857.    else {
  858.       rgba = rgbaIn;
  859.    }
  860.  
  861.    /* Texture */
  862.    ASSERT(ctx->Texture.Enabled);
  863.    ASSERT(texSets <= MAX_TEX_SETS);
  864.    for (i=0;i<texSets;i++) {
  865.       GLuint j = ctx->Texture.Set[i].TexCoordSet;
  866.       /* Evaluate i_th texture environment using the j_th set of
  867.        * texture coords
  868.        */
  869.       gl_texture_pixels( ctx, i, n, s[j], t[j], u[j], lambda[j], rgba );
  870.    }
  871.  
  872.  
  873.    /* Add base and specular colors */
  874.    if (spec && ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
  875.       add_colors( n, rgba, spec );   /* rgba = rgba + spec */
  876.  
  877.    /* Per-pixel fog */
  878.    if (ctx->Fog.Enabled && (primitive==GL_BITMAP || ctx->FogMode==FOG_FRAGMENT)) {
  879.       gl_fog_rgba_pixels( ctx, n, z, rgba );
  880.    }
  881.  
  882.    /* Do the scissor test */
  883.    if (ctx->Scissor.Enabled) {
  884.       if (gl_scissor_span( ctx, n, x, y, mask )==0) {
  885.      return;
  886.       }
  887.       write_all = GL_FALSE;
  888.    }
  889.  
  890.    /* Polygon Stippling */
  891.    if (ctx->Polygon.StippleFlag && primitive==GL_POLYGON) {
  892.       stipple_polygon_span( ctx, n, x, y, mask );
  893.       write_all = GL_FALSE;
  894.    }
  895.  
  896.    /* Do the alpha test */
  897.    if (ctx->Color.AlphaEnabled) {
  898.       if (gl_alpha_test( ctx, n, rgba, mask )==0) {
  899.      return;
  900.       }
  901.       write_all = GL_FALSE;
  902.    }
  903.  
  904.    if (ctx->Stencil.Enabled) {
  905.       /* first stencil test */
  906.       if (gl_stencil_span( ctx, n, x, y, mask )==0) {
  907.      return;
  908.       }
  909.       /* depth buffering w/ stencil */
  910.       gl_depth_stencil_span( ctx, n, x, y, z, mask );
  911.       write_all = GL_FALSE;
  912.    }
  913.    else if (ctx->Depth.Test) {
  914.       /* regular depth testing */
  915.       GLuint m = (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
  916.       if (m==0) {
  917.          return;
  918.       }
  919.       if (m<n) {
  920.          write_all = GL_FALSE;
  921.       }
  922.    }
  923.  
  924.    if (ctx->RasterMask & NO_DRAW_BIT) {
  925.       /* write no pixels */
  926.       return;
  927.    }
  928.  
  929.    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  930.       /* make backup of fragment colors */
  931.       MEMCPY( rgbaBackup, rgba, 4 * n * sizeof(GLubyte) );
  932.    }
  933.  
  934.    /* blending */
  935.    if (ctx->Color.SWLogicOpEnabled) {
  936.       gl_logicop_rgba_span( ctx, n, x, y, rgba, mask );
  937.    }
  938.    else  if (ctx->Color.BlendEnabled) {
  939.       gl_blend_span( ctx, n, x, y, rgba, mask );
  940.    }
  941.  
  942.    if (ctx->Color.SWmasking) {
  943.       gl_mask_rgba_span( ctx, n, x, y, rgba );
  944.    }
  945.  
  946.    /* write pixels */
  947.    (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, rgba, write_all ? Null : mask );
  948.    if (ctx->RasterMask & ALPHABUF_BIT) {
  949.       gl_write_alpha_span( ctx, n, x, y, rgba, write_all ? Null : mask );
  950.    }
  951.  
  952.    if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  953.       /* Also draw to back buffer */
  954.       (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  955.       if (ctx->Color.SWLogicOpEnabled) {
  956.          gl_logicop_rgba_span( ctx, n, x, y, rgba, mask );
  957.       }
  958.       else if (ctx->Color.BlendEnabled) {
  959.          gl_blend_span( ctx, n, x, y, rgba, mask );
  960.       }
  961.       if (ctx->Color.SWmasking) {
  962.          gl_mask_rgba_span( ctx, n, x, y, rgba );
  963.       }
  964.       (*ctx->Driver.WriteRGBASpan)( ctx, n, x, y, rgba, write_all ? Null : mask );
  965.       (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  966.       if (ctx->RasterMask & ALPHABUF_BIT) {
  967.          ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  968.          gl_write_alpha_span( ctx, n, x, y, rgba, write_all ? Null : mask );
  969.          ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  970.       }
  971.    }
  972. }
  973.  
  974.  
  975.  
  976. /*
  977.  * Read RGBA pixels from frame buffer.  Clipping will be done to prevent
  978.  * reading ouside the buffer's boundaries.
  979.  */
  980. void gl_read_rgba_span( GLcontext *ctx,
  981.                         GLuint n, GLint x, GLint y,
  982.                         GLubyte rgba[][4] )
  983. {
  984.    if (y<0 || y>=ctx->Buffer->Height || x>=ctx->Buffer->Width) {
  985.       /* completely above, below, or right */
  986.       MEMSET( rgba, 0, 4 * n * sizeof(GLubyte)); /*XXX maybe leave undefined?*/
  987.    }
  988.    else {
  989.       GLint skip, length;
  990.       if (x < 0) {
  991.          /* left edge clippping */
  992.          skip = -x;
  993.          length = (GLint) n - skip;
  994.          if (length < 0) {
  995.             /* completely left of window */
  996.             return;
  997.          }
  998.          if (length > ctx->Buffer->Width) {
  999.             length = ctx->Buffer->Width;
  1000.          }
  1001.       }
  1002.       else if ((GLint) (x + n) > ctx->Buffer->Width) {
  1003.          /* right edge clipping */
  1004.          skip = 0;
  1005.          length = ctx->Buffer->Width - x;
  1006.          if (length < 0) {
  1007.             /* completely to right of window */
  1008.             return;
  1009.          }
  1010.       }
  1011.       else {
  1012.          /* no clipping */
  1013.          skip = 0;
  1014.          length = (GLint) n;
  1015.       }
  1016.  
  1017.       (*ctx->Driver.ReadRGBASpan)( ctx, length, x + skip, y, rgba + skip );
  1018.       if (ctx->RasterMask & ALPHABUF_BIT) {
  1019.          gl_read_alpha_span( ctx, length, x + skip, y, rgba + skip );
  1020.       }
  1021.    }
  1022. }
  1023.  
  1024.  
  1025.  
  1026.  
  1027. /*
  1028.  * Read CI pixels from frame buffer.  Clipping will be done to prevent
  1029.  * reading ouside the buffer's boundaries.
  1030.  */
  1031. void gl_read_index_span( GLcontext *ctx,
  1032.                          GLuint n, GLint x, GLint y, GLuint indx[] )
  1033. {
  1034.    register GLuint i;
  1035.  
  1036.    if (y<0 || y>=ctx->Buffer->Height || x>=ctx->Buffer->Width) {
  1037.       /* completely above, below, or right */
  1038.       for (i=0;i<n;i++) {
  1039.      indx[i] = 0;
  1040.       }
  1041.    }
  1042.    else {
  1043.       GLint skip, length;
  1044.       if (x < 0) {
  1045.          /* left edge clippping */
  1046.          skip = -x;
  1047.          length = (GLint) n - skip;
  1048.          if (length < 0) {
  1049.             /* completely left of window */
  1050.             return;
  1051.          }
  1052.          if (length > ctx->Buffer->Width) {
  1053.             length = ctx->Buffer->Width;
  1054.          }
  1055.       }
  1056.       else if ((GLint) (x + n) > ctx->Buffer->Width) {
  1057.          /* right edge clipping */
  1058.          skip = 0;
  1059.          length = ctx->Buffer->Width - x;
  1060.          if (length < 0) {
  1061.             /* completely to right of window */
  1062.             return;
  1063.          }
  1064.       }
  1065.       else {
  1066.          /* no clipping */
  1067.          skip = 0;
  1068.          length = (GLint) n;
  1069.       }
  1070.  
  1071.       (*ctx->Driver.ReadCI32Span)( ctx, length, skip + x, y, indx + skip );
  1072.    }
  1073. }
  1074.